﻿using Common.Utils;
using Controller.Enum;
using Controller.Utils;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ControllerManageServer.Packet
{
    public class PradaActionPacketModel
    {
        #region 变量声明

        /// <summary>
        /// 数据帧头
        /// </summary>
        public static byte[] DATA_PACKET_HEAD = { 0xFC, 0xFD };
        /// <summary>
        /// 数据帧尾
        /// </summary>
        public static byte[] DATA_PACKET_TAIL = { 0xCF, 0xDF };

        /// <summary>
        /// 命令
        /// </summary>
        public PradaWatchCommunicationCommandEnum Command { get; set; }
        /// <summary>
        /// 解析是否成功
        /// </summary>
        private bool _isSuccess;
        /// <summary>
        /// 解析是否成功
        /// </summary>
        public bool IsSuccess { get { return _isSuccess; } }
        /// <summary>
        /// 文本编码
        /// </summary>
        public Encoding TextEncoding { get; set; } = Encoding.GetEncoding("GB2312");

        #endregion 变量声明

        #region 构造函数

        public PradaActionPacketModel() { 
        
        }

        #endregion 构造函数

        /// <summary>
        /// 数据体数据
        /// </summary>
        /// <returns></returns>
        protected virtual byte[] DataBody() {
            return null;
        }

        /// <summary>
        /// 解析数据体数据
        /// </summary>
        /// <param name="iData"></param>
        /// <param name="iStartPosition"></param>
        protected virtual void ParseDataBody(byte[] iData, ref int iStartPosition) {
            return;
        }

        /// <summary>
        /// 序列化
        /// </summary>
        public byte[] Serialize() {
            List<byte> result = new List<byte>();
            result.AddRange(DATA_PACKET_HEAD);
            /// 命令
            result.Add((byte)Command);
            /// 数据体
            byte[] tmp = DataBody();
            if (tmp != null || tmp.Length != 0) result.AddRange(tmp);
            /// 校验位
            result.Add(VerifyHelper.XOR(result.ToArray(), 2, result.Count - 2));
            /// 数据包尾
            result.AddRange(DATA_PACKET_TAIL);
            return result.ToArray();
        }

        /// <summary>
        /// 反序列化
        /// </summary>
        public void Unserialize(byte[] iBuffer) {
            int pos = 0;

            _isSuccess =  ByteArrayUtils.ComparisonTo(iBuffer, pos, DATA_PACKET_HEAD, 0, DATA_PACKET_HEAD.Length);
            if (!_isSuccess) return;
            pos += DATA_PACKET_HEAD.Length;
            
            Command = (PradaWatchCommunicationCommandEnum)iBuffer[pos];
            pos++;

            ParseDataBody(iBuffer, ref pos);

            if (/*Command != PradaWatchCommunicationCommandEnum.RFID_DATA &&*/ iBuffer[pos] != VerifyHelper.XOR(iBuffer, DATA_PACKET_HEAD.Length, pos - DATA_PACKET_HEAD.Length)) {
                _isSuccess = false;
                return;
            }
            pos++;

            _isSuccess = ByteArrayUtils.ComparisonTo(iBuffer, pos, DATA_PACKET_TAIL, 0, DATA_PACKET_TAIL.Length);
        }
    }

    /// <summary>
    /// RFID数据包的指令
    /// </summary>
    public class PradaRfidDataActionPacketModel : PradaActionPacketModel
    {
        /// <summary>
        /// RFID
        /// </summary>
        public uint Rfid { get; set; }

        public PradaRfidDataActionPacketModel()
        {
            Command = PradaWatchCommunicationCommandEnum.RFID_DATA;
        }

        /// <summary>
        /// 数据体数据
        /// </summary>
        /// <returns></returns>
        protected override byte[] DataBody()
        {
            return BitConverter.GetBytes(Rfid);
        }

        /// <summary>
        /// 解析数据体
        /// </summary>
        /// <param name="iData"></param>
        /// <param name="iStartPosition"></param>
        protected override void ParseDataBody(byte[] iData, ref int iStartPosition)
        {
            Rfid = BitConverter.ToUInt32(iData, iStartPosition);
            iStartPosition += sizeof(Int32);
        }
    }

    /// <summary>
    /// 显示数据包的指令
    /// </summary>
    public class PradaDisplayDataActionPacketModel : PradaActionPacketModel {
        /// <summary>
        /// X轴位置
        /// </summary>
        public byte PositionX { get; set; }
        /// <summary>
        /// Y轴位置
        /// </summary>
        public byte PositionY { get; set; }
        /// <summary>
        /// 字体大小
        /// </summary>
        public byte FontSize { get; set; } = 32;
        /// <summary>
        /// 显示数据
        /// </summary>
        public string DisplayData { get; set; }

        public PradaDisplayDataActionPacketModel() {
            Command = PradaWatchCommunicationCommandEnum.DISPLAY_DATA;
        }

        /// <summary>
        /// 数据体数据
        /// </summary>
        /// <returns></returns>
        protected override byte[] DataBody() {
            List<byte> result = new List<byte>
            {
                PositionX,
                PositionY,
                FontSize
            };

            byte[] tmp = TextEncoding.GetBytes(DisplayData);
            //result.AddRange(BitConverter.GetBytes(tmp.Length));
            if (tmp.Length != 0) {
                if(tmp.Length > 80)
                    result.AddRange(tmp.Take(80));
                else 
                    result.AddRange(tmp);
            }
            result.Add(0x00);

            return result.ToArray();
        }

        /// <summary>
        /// 解析数据体
        /// </summary>
        /// <param name="iData"></param>
        /// <param name="iStartPosition"></param>
        protected override void ParseDataBody(byte[] iData, ref int iStartPosition) {
            PositionX = iData[iStartPosition++];
            PositionY = iData[iStartPosition++];
            FontSize = iData[iStartPosition++];

            int len = iData.Length - iStartPosition - DATA_PACKET_TAIL.Length - 1;
            DisplayData = TextEncoding.GetString(iData, iStartPosition, len);
            iStartPosition += len;
        }
    }

    /// <summary>
    /// 带手表模块PANID和信道、班值的数据包
    /// </summary>
    public class PradaPanidChannelActionPacketModel : PradaActionPacketModel { 
        /// <summary>
        /// 手表模块PANID
        /// </summary>
        public byte Panid { get; set; }
        /// <summary>
        /// 信道
        /// </summary>
        public byte ChannelNumber { get; set; }
        /// <summary>
        /// 班值号
        /// </summary>
        public byte DutyNumber { get; set; }

        public PradaPanidChannelActionPacketModel() {
            Command = PradaWatchCommunicationCommandEnum.WRITE_PANID;
        }

        /// <summary>
        /// 数据体数据
        /// </summary>
        /// <returns></returns>
        protected override byte[] DataBody() {
            return new byte[] { Panid , ChannelNumber, DutyNumber};
        }

        /// <summary>
        /// 解析数据体
        /// </summary>
        /// <param name="iData"></param>
        /// <param name="iStartPosition"></param>
        protected override void ParseDataBody(byte[] iData, ref int iStartPosition)
        {
            Panid = iData[iStartPosition];
            iStartPosition++;

            ChannelNumber = iData[iStartPosition];
            iStartPosition++;

            DutyNumber = iData[iStartPosition];
            iStartPosition++;
        }
    }

    ///// <summary>
    ///// 带手表信道的数据包
    ///// </summary>
    //public class PradaWatchChannelActionPacketModel : PradaActionPacketModel { 
    //    /// <summary>
    //    /// 信道
    //    /// </summary>
    //    public ushort ChannelNumber { get; set; }

    //    /// <summary>
    //    /// 数据体数据
    //    /// </summary>
    //    /// <returns></returns>
    //    protected override byte[] DataBody() { 
    //        return BitConverter.GetBytes(ChannelNumber);
    //    }

    //    /// <summary>
    //    /// 解析数据体
    //    /// </summary>
    //    /// <param name="iData"></param>
    //    /// <param name="iStartPosition"></param>
    //    protected override void ParseDataBody(byte[] iData, ref int iStartPosition)
    //    {
    //        ChannelNumber = BitConverter.ToUInt16(iData, iStartPosition);
    //        iStartPosition += sizeof(ushort);
    //    }
    //}

    /// <summary>
    /// ACK数据包,手环→平板
    /// </summary>
    public class PradaWatchAckPacketModel: PradaActionPacketModel {
        #region 变量声明

        /// <summary>
        /// 应答ACK命令类型
        /// </summary>
        public PradaWatchCommunicationCommandEnum AckCommandType { get; set; }
        /// <summary>
        /// 值班号,0x41/0x42
        /// </summary>
        public byte DutyNumber { get; set; }
        /// <summary>
        /// 执行状态
        /// </summary>
        public bool ExecutionState { get; set; }

        #endregion 变量声明

        public PradaWatchAckPacketModel() {
            Command = PradaWatchCommunicationCommandEnum.ACK;
        }

        /// <summary>
        /// 数据体数据
        /// </summary>
        /// <returns></returns>
        protected override byte[] DataBody() {
            return new byte[] { (byte)AckCommandType, (byte)(ExecutionState ? 0x01 : 0x00) };
        }

        /// <summary>
        /// 解析数据体
        /// </summary>
        /// <param name="iData"></param>
        /// <param name="iStartPosition"></param>
        protected override void ParseDataBody(byte[] iData, ref int iStartPosition)
        {
            AckCommandType = (PradaWatchCommunicationCommandEnum)iData[iStartPosition++];
            DutyNumber = iData[iStartPosition];
            ExecutionState = iData[iStartPosition] == 0x01;
            iStartPosition++;
        }
    }

    /// <summary>
    /// 写RFID数据包,平板→平板
    /// </summary>
    public class PradaWriteRfidActionPacketModel: PradaActionPacketModel {
        /// <summary>
        /// RFID
        /// </summary>
        public UInt32 Rfid { get; set; }

        public PradaWriteRfidActionPacketModel() {
            Command = PradaWatchCommunicationCommandEnum.WRITE_RFID_DATA;
        }

        /// <summary>
        /// 数据体数据
        /// </summary>
        /// <returns></returns>
        protected override byte[] DataBody()
        {
            return BitConverter.GetBytes(Rfid);
        }

        /// <summary>
        /// 解析数据体
        /// </summary>
        /// <param name="iData"></param>
        /// <param name="iStartPosition"></param>
        protected override void ParseDataBody(byte[] iData, ref int iStartPosition)
        {
            Rfid = BitConverter.ToUInt32(iData, iStartPosition);
            iStartPosition += sizeof(UInt32);
        }
    }

    /// <summary>
    /// 手表振动的数据包
    /// </summary>
    public class PradaWatchActionPacketModel : PradaActionPacketModel { 
        /// <summary>
        /// 振动动作
        /// </summary>
        public byte Action { get; set; }
        /// <summary>
        /// 待定
        /// </summary>
        public byte DefaultAction { get; set; } = 0x01;

        public PradaWatchActionPacketModel() {
            Command = PradaWatchCommunicationCommandEnum.WATCH_ALARM;
        }

        protected override byte[] DataBody()
        {
            return new byte[] { Action, DefaultAction };
        }

        protected override void ParseDataBody(byte[] iData, ref int iStartPosition)
        {
            Action = iData[iStartPosition++];
            DefaultAction = iData[iStartPosition++];
        }
    }

    /// <summary>
    /// 请求显示数据
    /// </summary>
    public class PradaRequestDisplayDataPacketModel : PradaActionPacketModel { 
        /// <summary>
        /// 扩展字段
        /// </summary>
        public UInt16 ExtendData { get; set; }

        public PradaRequestDisplayDataPacketModel()
        {
            Command = PradaWatchCommunicationCommandEnum.REQUEST_DISPLAY_DATA;
        }

        protected override byte[] DataBody(){ 
            return BitConverter.GetBytes(ExtendData);
        }

        protected override void ParseDataBody(byte[] iData, ref int iStartPosition) { 
            ExtendData = BitConverter.ToUInt16(iData, iStartPosition);
            iStartPosition += 2;
        }
    }
}
